package basic;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * The Class Relation.
 */
public class Relation {

	/** The Constant ONETOONE. */
	public static final int ONETOONE = 0;

	/** The Constant ONETOALL. */
	public static final int ONETOALL = 1;

	/** The Constant ALLTOONE. */
	public static final int ALLTOONE = 2;

	/** The Constant ALLTOALL. */
	public static final int ALLTOALL = 3;

	/** The name of the relation. */
	private String name = "";

	/** The first entity of the relation. */
	private String entityStart = "";

	/** The second entity of the relation. */
	private String entityEnd = "";

	/** The start. */
	private Point start = null;

	/** The end. */
	private Point end = null;

	/** The list attribute. */
	private ArrayList<HashMap<String, String>> listAttr = new ArrayList<HashMap<String, String>>();

	/** The list of points that compose relation. */
	private ArrayList<Point> points = new ArrayList<Point>();

	/** The cardinality. */
	private int cardinality = -1; // (0: o2o, 1: o2all, 2: all2o, 3: all2all)

	/**
	 * Instantiates a new relation.
	 * 
	 * @param name
	 *            the name
	 * @param entityStart
	 *            the entity start
	 * @param entityEnd
	 *            the entity end
	 * @param cardinality
	 *            the cardinality
	 */
	public Relation(String name, String entityStart, String entityEnd,
			int cardinality) {
		this.name = name;
		this.entityStart = entityStart;
		this.entityEnd = entityEnd;
		this.cardinality = cardinality;
		this.start = new Point(0, 0);
		this.end = new Point(0, 0);
	}

	/**
	 * Instantiates a new relation.
	 * 
	 * @param name
	 *            the name
	 * @param entityStart
	 *            the entity start
	 * @param entityEnd
	 *            the entity end
	 * @param cardinality
	 *            the cardinality
	 */
	public Relation(String name, String entityStart, String entityEnd,
			String cardinality) {
		this.name = name;
		this.entityStart = entityStart;
		this.entityEnd = entityEnd;
		this.cardinality = convertCardinality(cardinality);
		this.start = new Point(0, 0);
		this.end = new Point(0, 0);
	}

	/**
	 * Convert cardinality.
	 * 
	 * @param card
	 *            the card
	 * @return an integer
	 */
	static public int convertCardinality(String card) {
		if (card.compareTo("one_to_one") == 0)
			return ONETOONE;
		else if (card.compareTo("one_to_all") == 0)
			return ONETOALL;
		else if (card.compareTo("all_to_one") == 0)
			return ALLTOONE;
		else if (card.compareTo("all_to_all") == 0)
			return ALLTOALL;
		else
			return -1;
	}

	/**
	 * Checks if is entity in relation.
	 * 
	 * @param ename
	 *            the entity name
	 * @return true, if is entity in relation
	 */
	public boolean isEntityInRelation(String ename) {
		for (int i = 0; i < listAttr.size(); i++) {
			if (listAttr.get(i).containsValue(ename))
				return true;
		}
		return false;
	}

	/**
	 * follows are setter/getter methods for end and start entity coordinates.
	 * 
	 * @return the start point
	 */
	public Point getStartPoint() {
		return this.start;
	}

	/**
	 * Gets the end point.
	 * 
	 * @return the end point
	 */
	public Point getEndPoint() {
		return this.end;
	}

	/**
	 * Gets points that compose line
	 * 
	 * @return list of point
	 */
	public ArrayList<Point> getPoints() {
		return this.points;
	}

	/**
	 * Sets the end point.
	 * 
	 * @param x
	 *            the x
	 * @param y
	 *            the y
	 */
	public void setEndPoint(int x, int y) {
		this.end.setLocation(x, y);
	}

	/**
	 * Sets the start point.
	 * 
	 * @param x
	 *            the x
	 * @param y
	 *            the y
	 */
	public void setStartPoint(int x, int y) {
		this.start.setLocation(x, y);
	}

	/**
	 * Adds attributes to relation.
	 * 
	 * @param en1
	 *            the en1
	 * @param attr1
	 *            the attr1
	 * @param en2
	 *            the en2
	 * @param attr2
	 *            the attr2
	 */
	public void addRelAttribute(String en1, String attr1, String en2,
			String attr2) {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put(en1, attr1);
		map.put(en2, attr2);
		listAttr.add(map);
	}

	/**
	 * Removes attributes to relation.
	 * 
	 * @param ename
	 *            the entity name
	 */
	public void removeAttributeRel(String ename) {
		for (int i = 0; i < listAttr.size(); i++) {
			if (listAttr.get(i).containsKey(ename))
				listAttr.get(i).remove(ename);
		}
	}

	/**
	 * Gets hash map from index.
	 * 
	 * @param index
	 *            the index
	 * @return the hash map from index
	 */
	public HashMap<String, String> getHashMapFromIndex(int index) {
		HashMap<String, String> map = null;
		if (0 <= index && index < this.listAttr.size())
			map = listAttr.get(index);
		return map;
	}

	/**
	 * Returns relations'attributes.
	 * 
	 * @return the relation attribute
	 */
	public ArrayList<HashMap<String, String>> getRelAttribute() {
		return this.listAttr;
	}

	/**
	 * Gets the entity start.
	 * 
	 * @return the entity start
	 */
	public String getEntityStart() {
		return this.entityStart;
	}

	/**
	 * Gets the entity end.
	 * 
	 * @return the entity end
	 */
	public String getEntityEnd() {
		return this.entityEnd;
	}

	/**
	 * Sets the en1 name.
	 * 
	 * @param name
	 *            the new en1 name
	 */
	public void setEn1Name(String name) {
		this.entityStart = name;
	}

	/**
	 * Sets the en2 name.
	 * 
	 * @param name
	 *            the new en2 name
	 */
	public void setEn2Name(String name) {
		this.entityStart = name;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Gets the cardinality.
	 * 
	 * @return the cardinality
	 */
	public int getCardinality() {
		return this.cardinality;
	}

	/**
	 * Gets the string cardinality.
	 * 
	 * @return the string cardinality
	 */
	public String[] getStringCardinality() {
		String[] card = new String[2];
		if (this.getCardinality() == Relation.ONETOONE) {
			card[0] = "1";
			card[1] = "1";
		} else if (this.getCardinality() == Relation.ONETOALL) {
			card[0] = "1";
			card[1] = "N";
		} else if (this.getCardinality() == Relation.ALLTOONE) {
			card[0] = "N";
			card[1] = "1";
		} else if (this.getCardinality() == Relation.ALLTOALL) {
			card[0] = "N";
			card[1] = "N";
		}
		return card;
	}
}
